package wordit.ea;

import java.util.LinkedList;
import java.util.List;

/**
 * The main entry point to this package. Orchestrates the creation of new
 * generations.
 * 
 */
public class EvolutionaryAlgorithm {
	private final Configuration configuration;
	private final StopFunction stopFunction;
	private List<EvolutionaryAlgorithmListener> evolutionaryAlgorithmListeners;

	public EvolutionaryAlgorithm(Configuration conf) {
		this.evolutionaryAlgorithmListeners = new LinkedList<EvolutionaryAlgorithmListener>();
		this.configuration = conf;
		this.stopFunction = conf.getStopFunction();

		if (stopFunction == null)
			throw new IllegalArgumentException("termination function not set");
	}

	/**
	 * Runs the EA to generate generations. Terminates when the stop-function
	 * (given in the configuration) says it should stop
	 * 
	 * @return the best genome found
	 */
	public void run() {
		notifyStart();
		
		Generation currentGeneration = Generation.createFirstGeneration(
				configuration, configuration.getGenerationSize());
		notifyNewGeneration(currentGeneration);

		while (!stopFunction.shouldStop(currentGeneration)) {
			currentGeneration = currentGeneration.nextGeneration();
			notifyNewGeneration(currentGeneration);
		}

		notifyStopped();
	}

	private void notifyStart() {
		for (EvolutionaryAlgorithmListener l : evolutionaryAlgorithmListeners)
			l.onStart();
	}
	
	private void notifyStopped() {
		for (EvolutionaryAlgorithmListener l : evolutionaryAlgorithmListeners)
			l.onStop();
	}

	public void addEvolutionaryAlgorithmListener(EvolutionaryAlgorithmListener l) {
		evolutionaryAlgorithmListeners.add(l);
	}
	
	private void notifyNewGeneration(Generation newGeneration) {
		for (EvolutionaryAlgorithmListener l : evolutionaryAlgorithmListeners)
			l.onNewGeneration(newGeneration);
	}
}
